#ifndef SYNTAX_H
#define SYNTAX_H

#include <vector>
#include <iostream>
#include <map>
#include <sstream>
#include <set>
#include <stack>

#include "ffile.hpp"
#include "flexical.hpp"

#ifndef PRODUCE_MAX_SIZE 
#define PRODUCE_MAX_SIZE 7
#endif
#ifndef NULL_WORD 
#define NULL_WORD "@"
#endif

/*
 *  map容器拷贝，主要用于创建first和follow集合时使用
 *  将value2中的数据拷贝到value1中
 */
#ifndef CP_MAP
#define CP_FIRST_MAP(_value1, _value2) \
        for(std::set<std::string>::iterator _iter = First[_value2].begin();\
            _iter!=First[_value2].end();_iter++)    \
            {   \
                if(*_iter != NULL_WORD) \
                    First[_value1].insert(*_iter); \
            }   
#endif

namespace fairy{
class Fsyntax
{
    //一个产生式的结构
    struct Produce{
        std::string origin;
        //产生式后面的那个串
        std::string array[PRODUCE_MAX_SIZE];
        //产生式的长度
        int length;
    };

    //非终结符递归时用的结构体，在从文法的起始符开始，向下递归，没进入一次，层级+1
    struct NonTerminatorLeave{
        std::string str;
        int leave;
    };
    //非终结符栈，同上，用于创建first结合是递归使用
    std::stack<NonTerminatorLeave> nonTerminatorStack;


public:
    typedef std::vector<Produce> GP;
    typedef std::map<std::string, std::set<std::string> > FirstMap;
    typedef std::map<std::string, std::set<std::string> > FollowMap;

private:
    //从文法产生式中自动检测终结符
    auto make_terminator() -> void;
    //从文法产生式中自动检测非终结符
    auto make_non_terminator() -> void;
    //从产生式中找出可以推导出的第一个终结符
    auto find_terminator(std::string, int) -> int;
    //判断一个符号是否是终结符
    inline auto is_terminator(std::string value) -> bool{ return terminators.count(value) ? true :false; }

public:
    Fsyntax();
    ~Fsyntax();
    //构造first集
    auto make_first() -> void;
    //构造follow集合
    auto make_follow() -> void;

public:
    auto display_grammer() -> void;
    //查看终结符集合
    auto display_terminator() -> void;
    //查看非终结符集合
    auto display_non_terminator() -> void;
    //查看first集合
    auto display_first() -> void;
private:
    //文件操作
    Ffile fairy;
    //文法池，一条数据是一个产生式
    std::vector<Produce> grammerPool;
    //终结符集合,用于构造First和Follow集合,下同
    std::set<std::string> terminators;
    //非终结符集合
    std::set<std::string>  nonTerminators;
    //First集合
    FirstMap First;
    //Follow集合
    FollowMap Follow;

};

}



#endif
